<?php


class IConfig extends IObject {
	private $opts = array();
	private static $modules = array();
	
	public function __construct($file) {
		if (is_file($file)) {
			$array = require(realpath($file));
			if (!is_array($array)) {
				throw new IException("invalid config file '{$file}'");
			}
			$this->opts = $array;
		}
	}
	
	
	/**
	 * Enter description here...
	 *
	 * @param unknown_type $module
	 * @return IConfig
	 */
	public static function &module($module) {
		if (array_key_exists($module, self::$modules)) {
			return self::$modules[$module];
		}
		
		//默认配置
		$defaultFile = IF_FW_DIR . "/config/_{$module}_default.php";
		$default = null;
		if (is_file($defaultFile)) {
			$default = new IConfig($defaultFile);
		}
		
		//模块中定义的
		if ($module != "app") {
			$modulesInApp = self::opt("@app.modules");
			if (!empty($modulesInApp) && isset($modulesInApp[$module])) {
				$configFile = IF_FW_DIR . "/" . $modulesInApp[$module] . "/_config.php";
				if (is_file($configFile)) {
					$default = new IConfig($configFile);
				}
			}
			else {
				$_3rdModulesInApp = self::opt("@app.3rd_modules");
				if (!empty($_3rdModulesInApp) && isset($_3rdModulesInApp[$module])) {
					$configFile = IF_APP_ROOT . "/" . $_3rdModulesInApp[$module] . "/_config.php";
					if (is_file($configFile)) {
						$default = new IConfig($configFile);
					}
				}
			}
		}
		
		//用户自定义的
		$file = IApplication::singleton()->root() . "/config/_{$module}.php";
		$config = new IConfig($file);
		
		//合并
		if ($default != null) {
			$opts = array_merge($default->opts(), $config->opts());
			$config->setOpts($opts);
		}
		
		self::$modules[$module] = &$config;
		return $config;
	}
	
	public static function opt($key) {
		$pieces = explode(".", $key);
		if (empty($pieces) || !preg_match("/^@/", $pieces[0])) {
			throw new IException("'{$key}' must define a module name(such as @router)");
		}
		$module = substr(array_shift($pieces), 1);
		if (empty($pieces)) {
			return self::module($module)->opts();
		}
		else {
			return self::module($module)->get(implode(".", $pieces));
		}
	}
	
	public function opts() {
		return $this->opts;
	}
	
	public function setOpts(array $opts) {
		$this->opts = $opts;
	}
	
	public function get($key) {
		$config = $this->opts;
		$keys = explode(".", $key);
		if (count($keys) == 1) {
			return array_key_exists($keys[0], $config)?$config[$keys[0]]:null;
		}
		
		$lastKey = array_pop($keys);
		$lastArray = $config;
		foreach ($keys as $key) {
			if (is_array($lastArray) && array_key_exists($key, $lastArray)) {
				$lastArray = $lastArray[$key];
			}
			else {
				return null;
			}
		}
		
		return array_key_exists($lastKey, $lastArray)?$lastArray[$lastKey]:null; 
	}
	
	public function set($key, $value) {
		$keys = explode(".", $key);
		if (count($keys) == 1) {
			$this->opts[$keys[0]] = $value;
			return true;
		}
		$lastKey = array_pop($keys);
		$lastConfig = &$this->opts;
		foreach ($keys as $key) {
			if (!isset($lastConfig[$key]) || !is_array($lastConfig[$key])) {
				$lastConfig[$key] = array();
			}
			$lastConfig = &$lastConfig[$key];
		}
		$lastConfig[$lastKey] = $value;
		return true;
	}
}

?>